package com.hudson.codec.proto;

import com.hudson.codec.SerializableMethodEnum;
import com.hudson.codec.proto.domain.RemotingCommandProto;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @Author: 渔小鲤
 * @DateTime: 2025/7/21 20:56
 **/
public class HudsonMQCodec4ProtoBuf extends ByteToMessageCodec<RemotingCommandProto.RemotingCommand> {
    private static final String magicStr = "Hudson";
    private static final byte[] magicBytes = magicStr.getBytes(StandardCharsets.UTF_8);
    private static final byte version = 0;
    private static final byte serializableMethod = SerializableMethodEnum.PROTO.getSerializableMethod();

    private static final Logger logger = LoggerFactory.getLogger(HudsonMQCodec4ProtoBuf.class);

    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, RemotingCommandProto.RemotingCommand remotingCommand, ByteBuf byteBuf) throws Exception {
        logger.debug("{}", remotingCommand);


        // 魔数  Hudson
        byteBuf.writeBytes(magicBytes);
        // 版本 0
        byteBuf.writeByte(version);
        byteBuf.writeByte(serializableMethod);
        logger.debug("{}", remotingCommand.toString());
        byte[] byteArray = remotingCommand.toByteArray();
        logger.debug("{}", byteArray.length);

        byteBuf.writeInt(byteArray.length);
        byteBuf.writeBytes(byteArray);
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        ByteBuf magic = byteBuf.readBytes(6);
        byte version = byteBuf.readByte();
        byte serializableMethod = byteBuf.readByte();

        int length = byteBuf.readInt();
        ByteBuf message = byteBuf.readBytes(length);
        RemotingCommandProto.RemotingCommand remotingCommand;
        try {
            remotingCommand = RemotingCommandProto.RemotingCommand.parseFrom(message.nioBuffer());
            list.add(remotingCommand);
        } finally {
            // 确保message被正确释放
            if (message.refCnt() > 0) {
                message.release();
            }
        }

        logger.debug("{},{},{},{},{}", magic.toString(StandardCharsets.UTF_8), version, serializableMethod, length, remotingCommand);
        // 释放其他ByteBuf
        if (magic.refCnt() > 0) {
            magic.release();
        }
    }
}
